<template>
  <div class="bg">
    <canvas ref="canvas"></canvas>
    <div class="items">
      <!-- 现在时间 -->
      <div class="item fitem">
        <div class="text hour">{{ hour }}</div>
        <div class="h">时</div>
      </div>
      <!-- <span class="ge">:</span> -->
      <div class="item sitem">
        <div class="text minute">{{ minute }}</div>
        <span class="m">分</span>
      </div>
      <!-- <span class="ge">:</span> -->
      <div class="item titem">
        <div class="text second">{{ second }}</div>
        <span class="s">秒</span>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, Ref } from "vue";
const year = ref(String(getNowTime().year));
const month = ref(getNowTime().month);
const day = ref(getNowTime().Day);
const hour = ref(getNowTime().hour);
const minute = ref(getNowTime().minute);
const second = ref(getNowTime().second);

// 创建时间补0函数
function addZero(timeNum: number): string {
  return timeNum < 10 ? `0${timeNum}` : timeNum.toString();
}

// 星期转中文函数
function weekDayChina(weekDay: number | null = null): string | null {
  switch (weekDay) {
    case 1:
      return "一";
    case 2:
      return "二";
    case 3:
      return "三";
    case 4:
      return "四";
    case 5:
      return "五";
    case 6:
      return "六";
    case 0:
      return "日";
    default:
      return null;
  }
}

// 格式化时间函数
function getNowTime(): {
  year: number;
  month: string;
  Day: string;
  hour: string;
  minute: string;
  second: string;
  weekDay: string | null;
} {
  const now = new Date();
  const year = now.getFullYear();
  const month = addZero(now.getMonth() + 1);
  const day = addZero(now.getDate());
  const hour = addZero(now.getHours());
  const minute = addZero(now.getMinutes());
  const second = addZero(now.getSeconds());
  const weekDay = weekDayChina(now.getDay());
  return { year, month, Day: day, hour, minute, second, weekDay };
}

// 页面文本渲染封装函数
function changeTime(ref: Ref<string>, value: string) {
  ref.value = value;
}

interface Particle {
  x: number;
  y: number;
  vex: number;
  vey: number;
  size: number;
  color: string;
}

const canvas = ref<HTMLCanvasElement | null>(null);
const ctx = ref<CanvasRenderingContext2D | null>(null);
const part = 240;
const line = 120;
const colorRgb = "245,250,224";
let particles: Particle[] = [];
let interaction: Particle | null = null;

class Particle {
  x: number;
  y: number;
  vex: number;
  vey: number;
  size: number;
  color: string;

  constructor(
    x: number,
    y: number,
    vex: number,
    vey: number,
    size: number,
    color: string
  ) {
    this.x = x;
    this.y = y;
    this.vex = vex;
    this.vey = vey;
    this.size = size;
    this.color = color;
  }

  draw() {
    if (!ctx.value) return;
    ctx.value.beginPath();
    ctx.value.arc(this.x, this.y, this.size, 0, Math.PI * 2);
    ctx.value.fillStyle = this.color;
    ctx.value.fill();
  }

  update() {
    if (!canvas.value) return;
    if (this.x < 0 || this.x > canvas.value.width) {
      this.vex *= -1;
      this.vey *= -1;
    }
    if (this.y < 0 || this.y > canvas.value.height) {
      this.vey *= -1;
    }
    this.x += this.vex;
    this.y += this.vey;
    this.draw();
  }
}

function getRand(min: number, max: number): number {
  return Math.random() * (max - min) + min;
}

function creatPart() {
  if (!canvas.value) return;
  for (let i = 0; i < part; i++) {
    let size = getRand(1, 3);
    let x = Math.random() * canvas.value.width;
    let y = Math.random() * canvas.value.height;
    let velox = getRand(-2, 2);
    let veloy = getRand(-2, 2);
    let color = `rgba(${colorRgb},${1 - size / 3})`;
    particles.push(new Particle(x, y, velox, veloy, size, color));
  }
}

function connnect() {
  if (!ctx.value) return;
  for (let i = 0; i < particles.length; i++) {
    for (let j = i + 1; j < particles.length; j++) {
      const p1 = particles[i];
      const p2 = particles[j];
      let distance = Math.sqrt(
        Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)
      );
      if (distance < line) {
        ctx.value.strokeStyle = `rgba(${colorRgb},${1 - distance / line})`;
        ctx.value.beginPath();
        ctx.value.lineWidth = 0.8;
        ctx.value.moveTo(p1.x, p1.y);
        ctx.value.lineTo(p2.x, p2.y);
        ctx.value.stroke();
      }
    }
  }
}

function animate() {
  if (!ctx.value || !canvas.value) return;
  requestAnimationFrame(animate);
  ctx.value.clearRect(0, 0, canvas.value.width, canvas.value.height);
  particles.forEach((particle) => {
    particle.update();
  });
  connnect();
}

function bindEvents() {
  canvas.value?.addEventListener("mouseover", (e) => {
    if (!interaction) {
      interaction = new Particle(e.x, e.y, 0, 0, 2, `rgba(${colorRgb},1)`);
      particles.push(interaction);
    }
  });

  canvas.value?.addEventListener("mousemove", (e) => {
    if (interaction) {
      interaction.x = e.x;
      interaction.y = e.y;
    }
  });

  canvas.value?.addEventListener("mouseout", (_e) => {
    interaction = null;
  });
}

// 创建定时器，每1s对数据进行一次渲染！
onMounted(() => {
  if (canvas.value) {
    ctx.value = canvas.value.getContext("2d");
    canvas.value.width = window.innerWidth;
    canvas.value.height = window.innerHeight;
  }
  creatPart();
  bindEvents();
  animate();

  setInterval(() => {
    const nowTime = getNowTime();
    changeTime(year, nowTime.year.toString());
    changeTime(month, nowTime.month);
    changeTime(day, nowTime.Day);
    changeTime(hour, nowTime.hour);
    changeTime(minute, nowTime.minute);
    changeTime(second, nowTime.second);
  }, 1000);
});
</script>

<style lang="scss" scoped>
$bg-color: black;
$border-color: #fff;
$hover-border-color: rebeccapurple;
$hover-border-color-2: rgb(32, 53, 219);
$hover-border-color-3: rgb(165, 37, 63);
$font-family: "楷体";
$transition-duration: 0.5s;

.bg {
  background-color: $bg-color;
  width: 100vw;
  height: 100vh;

  .items {
    position: absolute;
    top: 10vw;
    left: 55vh;
    margin: 150px auto;
    width: 800px;
    height: 450px;
    display: flex;
    justify-content: space-around;
    align-items: center;
    color: #fff;

    .item {
      width: 30%;
      height: 90%;
      text-align: center;
      border: 3px solid $border-color;
      transition: box-shadow $transition-duration ease, all $transition-duration;
      border-radius: 0;

      .text {
        line-height: 200px;
        padding-top: 80px;
      }

      .h,
      .m,
      .s {
        transition: all $transition-duration;
        font-size: 2rem;
        font-family: $font-family;
        opacity: 0;
      }
    }

    .fitem:hover {
      border: 3px solid $hover-border-color;
      border-radius: 30px 0 30px 0;

      .text {
        font-size: 9rem;
        color: $hover-border-color;
      }

      .h {
        opacity: 1;
      }
    }

    .sitem:hover {
      border: 3px solid $hover-border-color-2;
      border-radius: 30px 30px 0 0;

      .m {
        opacity: 1;
      }

      .text {
        font-size: 9rem;
        color: $hover-border-color-2;
      }
    }

    .titem:hover {
      border: 3px solid $hover-border-color-3;
      border-radius: 0 30px 0 30px;

      .s {
        opacity: 1;
      }

      .text {
        font-size: 9rem;
        color: $hover-border-color-3;
      }
    }

    .ge {
      font-size: 7rem;
    }

    .item > .text {
      font-size: 7rem;
      color: #fff;
      transition: all $transition-duration;
    }
  }
}
</style>
